﻿using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Linq.Dynamic;
using System.Text;
using System.Threading.Tasks;
using Abp;
using Abp.Application.Services.Dto;
using Abp.Authorization;
using Abp.AutoMapper;
using Abp.Configuration;
using Abp.Domain.Repositories;
using Abp.Extensions;
using Abp.Linq.Extensions;
using LeadThing.AbpZeroTemplate.BasicPersons.Authorization;
using LeadThing.AbpZeroTemplate.BasicPersons.Dtos;
using LeadThing.AbpZeroTemplate.Dto;
using LeadThing.AbpZeroTemplate.Areas;
using LeadThing.AbpZeroTemplate.Authorization.Roles.Dto;
using Abp.Runtime.Session;
using LeadThing.AbpZeroTemplate.Authorization.Roles;
using LeadThing.AbpZeroTemplate.Authorization.Users;

namespace LeadThing.AbpZeroTemplate.BasicPersons
{
    /// <summary>
    /// 莒县人口基本信息服务实现
    /// </summary>


    public class BasicPersonAppService : AbpZeroTemplateAppServiceBase, IBasicPersonAppService
    {
        private readonly IRepository<BasicPerson, long> _basicPersonRepository;
        private readonly IBasicPersonListExcelExporter _basicPersonListExcelExporter;
        private readonly IRepository<Area, long> _areaRepository;
        private readonly IRepository<User, long> _userRepository;//用户
        private readonly IRoleAppService _roleService;//角色
        private readonly ISqlExecuter _sqlExecuter;//sql语句接口



        private readonly BasicPersonManage _basicPersonManage;
        /// <summary>
        /// 构造方法
        /// </summary>
        public BasicPersonAppService(IRepository<BasicPerson, long> basicPersonRepository,
        BasicPersonManage basicPersonManage
      , IBasicPersonListExcelExporter basicPersonListExcelExporter
      , IRepository<Area, long> areaRepository
      , IRepository<User, long> userRepository
      , IRoleAppService roleService
      , ISqlExecuter sqlExecuter
  )
        {
            _basicPersonRepository = basicPersonRepository;
            _basicPersonManage = basicPersonManage;
            _basicPersonListExcelExporter = basicPersonListExcelExporter;
            _areaRepository = areaRepository;
            _userRepository = userRepository;
            _roleService = roleService;
            _sqlExecuter = sqlExecuter;
        }


        #region 实体的自定义扩展方法
        private IQueryable<BasicPerson> _basicPersonRepositoryAsNoTrack => _basicPersonRepository.GetAll().AsNoTracking();

        /// <summary>
        /// 根据条件获取实有房屋人口数据加载页面数据
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public PagedResultDto<BasicPersonPageListDto> GetAllBasicPersonLoadPage(GetBasicPersonInput input)
        {
            StringBuilder sb = new StringBuilder();

            sb.AppendFormat(@" select TOP {0} *,
                        'SexName' = case Sex when 1 then '男' else '女' end,
                        'MartyrName' = case IsMartyr when 1 then '是' else '否' end,
                        'AllowanceName' = case Isallowance when 1 then '是' else '否' end,
                        'LonelyName' = case IsLonely when 1 then '是' else '否' end,
                        'ElderlyName' = case Iselderly when 1 then '是' else '否' end,
                        'FiveGuaranteesName' = case IsFiveGuarantees when 1 then '是' else '否' end,
                        'PoliticsName' = case Politics when '1' then '党员' when '2' then '团员' else '群众' end,
                        'TownTitle' = (select Title from Basic.Area where id = b.TownID),
                        'AreaTitle' = (select Title from Basic.Area where id = b.AreaID),
                        'VillageTitle' = (select Title from Basic.Area where id = b.VillageID),
                        'XPoint' =
                            CASE
                                WHEN [VillageID] > 0 THEN (select top 1 XPoint from Basic.Area where Id = [VillageID])
                                WHEN [AreaID] > 0 THEN (select top 1 XPoint from Basic.Area where Id = [AreaID])
                                WHEN [TownID] > 0 THEN (select top 1 XPoint from Basic.Area where Id = [TownID])
                                ELSE ''
                            END,
                         'YPoint' =
                            CASE
                                WHEN [VillageID] > 0 THEN (select top 1 YPoint from Basic.Area where Id = [VillageID])
                                WHEN [AreaID] > 0 THEN (select top 1 YPoint from Basic.Area where Id = [AreaID])
                                WHEN [TownID] > 0 THEN (select top 1 YPoint from Basic.Area where Id = [TownID])
                                ELSE ''
                            END
                        from Basic.BasicPerson as b where isDeleted=0 and ParentID =", input.MaxResultCount);
            sb.Append(input.ParentID);

            var query = _basicPersonRepositoryAsNoTrack;
            query = query.Where(u => u.ParentID == input.ParentID);
            string skip = " and Id not in(select top " + input.SkipCount + " Id from Basic.BasicPerson where isDeleted=0 and ParentID =" + input.ParentID + " {0})";
            string skip1 = "";

            if (!string.IsNullOrWhiteSpace(input.FilterText))
            {
                sb.Append(" and Name like '%");
                sb.Append(input.FilterText);
                sb.Append("%' ");
                skip1 += string.Format(" and Name like '%{0}%'", input.FilterText);
                query = query.Where(u => u.Name.Contains(input.FilterText));
            }
            var count = query.Count();
            if (skip1 != "")
            {
                skip = string.Format(skip, skip1);
            }
            else
            {
                skip = skip.Replace("{0}", "");
            }
            var list = _sqlExecuter.SqlQuery<BasicPersonPageListDto>(sb.ToString() + skip).ToList();

            return new PagedResultDto<BasicPersonPageListDto>(count, list);
        }

        /// <summary>
        /// 根据ParentID获取数据
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<ListResultDto<BasicPersonListDto>> GetAllBasicPersonByParentID(BasicPersonListDto input)
        {
            var query = _basicPersonRepositoryAsNoTrack.Where(p => p.Id == input.Id || p.ParentID == input.Id);
            var items = await query.ToListAsync();
            var areaList = _areaRepository.GetAll();
            return new ListResultDto<BasicPersonListDto>(
                items.Select(item =>
                {
                    var dto = item.MapTo<BasicPersonListDto>();
                    var townModel = areaList.Where(p => p.Id == dto.TownID).Select(p => new { p.Title }).FirstOrDefault();
                    if (townModel != null)
                        dto.TownTitle = townModel.Title;

                    var areaModel = areaList.Where(p => p.Id == dto.AreaID).Select(p => new { p.Title }).FirstOrDefault();
                    if (areaModel != null)
                        dto.AreaTitle = areaModel.Title;

                    var villModel = areaList.Where(p => p.Id == dto.VillageID).Select(p => new { p.Title }).FirstOrDefault();
                    if (villModel != null)
                        dto.VillageTitle = villModel.Title;
                    return dto;
                }).ToList());
        }

        #endregion


        #region 莒县人口基本信息管理

        /// <summary>
        /// 根据查询条件获取莒县人口基本信息分页列表
        /// </summary>
        [AbpAuthorize(BasicPersonAppPermissions.BasicPerson)]
        public async Task<PagedResultDto<BasicPersonListDto>> GetPagedBasicPersonsAsync(GetBasicPersonInput input)
        {
            //只展示户主数据
            //var query = _basicPersonRepositoryAsNoTrack.Where(p => p.ParentID == 0);
            var query = _basicPersonRepositoryAsNoTrack;
            if (!string.IsNullOrWhiteSpace(input.FilterText))
            {
                query = query.Where(p => p.Name.Contains(input.FilterText));
            }



            //TODO:根据传入的参数添加过滤条件
            #region TODO:根据传入的参数添加过滤条件

            #region 权限验证

            var userID = AbpSession.GetUserId();
            var userModel = _userRepository.FirstOrDefault(userID);
            GetRolesInput input_role = new GetRolesInput() { UserId = userID };
            var role = await _roleService.GetRolesByUserId(input_role);

            if (role.DisplayName == "乡镇网格管理员")
                query = query.Where(p => p.TownID == userModel.TownID || p.CreatorUserId == userID);
            else if (role.DisplayName == "社区网格管理员")
                query = query.Where(p => p.AreaID == userModel.AreaID || p.CreatorUserId == userID);
            else if (role.DisplayName == "村庄网格管理员")
                query = query.Where(p => p.VillageID == userModel.VillageID || p.CreatorUserId == userID);

            #endregion

            //当事人
            if (!string.IsNullOrWhiteSpace(input.Name))
                query = query.Where(p => p.Name.Contains(input.Name));


            //镇
            if (input.TownID != 0)
                query = query.Where(p => p.TownID == input.TownID);

            //区
            if (input.AreaID != 0)
                query = query.Where(p => p.AreaID == input.AreaID);

            //村庄
            if (input.VillageID != 0)
                query = query.Where(p => p.VillageID == input.VillageID);

            #endregion

            var basicPersonCount = await query.CountAsync();

            var items = await query
            .OrderByDescending(p => p.Id)
            .PageBy(input)
            .ToListAsync();

            var areaList = _areaRepository.GetAll();
            return new PagedResultDto<BasicPersonListDto>(basicPersonCount,
                items.Select(item =>
                {
                    var dto = item.MapTo<BasicPersonListDto>();
                    var townModel = areaList.Where(p => p.Id == dto.TownID).Select(p => new { p.Title }).FirstOrDefault();
                    if (townModel != null)
                        dto.TownTitle = townModel.Title;

                    var areaModel = areaList.Where(p => p.Id == dto.AreaID).Select(p => new { p.Title }).FirstOrDefault();
                    if (areaModel != null)
                        dto.AreaTitle = areaModel.Title;

                    var villModel = areaList.Where(p => p.Id == dto.VillageID).Select(p => new { p.Title }).FirstOrDefault();
                    if (villModel != null)
                        dto.VillageTitle = villModel.Title;

                    if (dto.ParentID == 0)
                        dto.IsShow = true;
                    else
                        dto.IsShow = false;
                    return dto;
                }).ToList());
        }

        /// <summary>
        /// 通过Id获取莒县人口基本信息信息进行编辑或修改 
        /// </summary>
        [AbpAuthorize(BasicPersonAppPermissions.BasicPerson)]
        public async Task<GetBasicPersonForEditOutput> GetBasicPersonForEditAsync(NullableIdDto<long> input)
        {
            var output = new GetBasicPersonForEditOutput();

            BasicPersonEditDto basicPersonEditDto;

            if (input.Id.HasValue)
            {
                var entity = await _basicPersonRepository.GetAsync(input.Id.Value);
                basicPersonEditDto = entity.MapTo<BasicPersonEditDto>();
            }
            else
            {
                basicPersonEditDto = new BasicPersonEditDto();
            }

            output.BasicPerson = basicPersonEditDto;
            return output;
        }


        /// <summary>
        /// 通过指定id获取莒县人口基本信息ListDto信息
        /// </summary>
        [AbpAuthorize(BasicPersonAppPermissions.BasicPerson)]
        public async Task<BasicPersonListDto> GetBasicPersonByIdAsync(EntityDto<long> input)
        {
            var entity = await _basicPersonRepository.GetAsync(input.Id);

            return entity.MapTo<BasicPersonListDto>();
        }







        /// <summary>
        /// 新增或更改莒县人口基本信息
        /// </summary>
        [AbpAuthorize(BasicPersonAppPermissions.BasicPerson)]
        public async Task CreateOrUpdateBasicPersonAsync(CreateOrUpdateBasicPersonInput input)
        {
            if (input.BasicPersonEditDto.Id.HasValue)
            {
                await UpdateBasicPersonAsync(input.BasicPersonEditDto);
            }
            else
            {
                await CreateBasicPersonAsync(input.BasicPersonEditDto);
            }
        }

        /// <summary>
        /// 新增莒县人口基本信息
        /// </summary>
        [AbpAuthorize(BasicPersonAppPermissions.BasicPerson_CreateBasicPerson)]
        public virtual async Task<BasicPersonEditDto> CreateBasicPersonAsync(BasicPersonEditDto input)
        {
            //TODO:新增前的逻辑判断，是否允许新增

            var entity = input.MapTo<BasicPerson>();

            entity = await _basicPersonRepository.InsertAsync(entity);
            return entity.MapTo<BasicPersonEditDto>();
        }

        /// <summary>
        /// 编辑莒县人口基本信息
        /// </summary>
        [AbpAuthorize(BasicPersonAppPermissions.BasicPerson_EditBasicPerson)]
        public virtual async Task UpdateBasicPersonAsync(BasicPersonEditDto input)
        {
            //TODO:更新前的逻辑判断，是否允许更新

            var entity = await _basicPersonRepository.GetAsync(input.Id.Value);
            input.MapTo(entity);

            await _basicPersonRepository.UpdateAsync(entity);
        }

        /// <summary>
        /// 删除莒县人口基本信息
        /// </summary>
        [AbpAuthorize(BasicPersonAppPermissions.BasicPerson_DeleteBasicPerson)]
        public async Task DeleteBasicPersonAsync(EntityDto<long> input)
        {
            //TODO:删除前的逻辑判断，是否允许删除
            //先删除子节点
            await _basicPersonRepository.DeleteAsync(s => s.ParentID == input.Id);

            await _basicPersonRepository.DeleteAsync(input.Id);
        }

        /// <summary>
        /// 批量删除莒县人口基本信息
        /// </summary>
        [AbpAuthorize(BasicPersonAppPermissions.BasicPerson_DeleteBasicPerson)]
        public async Task BatchDeleteBasicPersonAsync(List<long> input)
        {
            //TODO:批量删除前的逻辑判断，是否允许删除
            await _basicPersonRepository.DeleteAsync(s => input.Contains(s.Id));
        }

        #endregion

        #region 莒县人口基本信息的Excel导出功能

        public async Task<FileDto> GetBasicPersonToExcel()
        {
            var entities = await _basicPersonRepository.GetAll().ToListAsync();

            var dtos = entities.MapTo<List<BasicPersonListDto>>();

            var fileDto = _basicPersonListExcelExporter.ExportBasicPersonToFile(dtos);



            return fileDto;
        }

        #endregion

        #region APP接口

        /// <summary>
        /// 根据查询条件获取莒县人口基本信息分页列表
        /// </summary>
        public async Task<PagedResultDto<BasicPersonListDto>> GetPagedBasicPersonsAppAsync(GetBasicPersonAPPInput input)
        {
            var _pageIndex = Convert.ToInt32(input.PageIndex);
            var _pageSize = Convert.ToInt32(input.PageSize);
            //只展示户主数据
            //var query = _basicPersonRepositoryAsNoTrack.Where(p => p.ParentID == 0);
            var query = _basicPersonRepositoryAsNoTrack;

            //TODO:根据传入的参数添加过滤条件
            #region TODO:根据传入的参数添加过滤条件

            #region 权限验证

            var userID = Convert.ToInt32(input.UserID);
            var userModel = _userRepository.FirstOrDefault(userID);
            GetRolesInput input_role = new GetRolesInput() { UserId = userID };
            var role = await _roleService.GetRolesByUserId(input_role);

            if (role.DisplayName == "乡镇网格管理员")
                query = query.Where(p => p.TownID == userModel.TownID || p.CreatorUserId == userID);
            else if (role.DisplayName == "社区网格管理员")
                query = query.Where(p => p.AreaID == userModel.AreaID || p.CreatorUserId == userID);
            else if (role.DisplayName == "村庄网格管理员")
                query = query.Where(p => p.VillageID == userModel.VillageID || p.CreatorUserId == userID);

            #endregion

            //当事人
            if (!string.IsNullOrWhiteSpace(input.Name))
                query = query.Where(p => p.Name.Contains(input.Name));

            #endregion

            var basicPersonCount = await query.CountAsync();

            var items = await query
            .OrderByDescending(p => p.Id)
            .Take(_pageSize * _pageIndex).Skip(_pageSize * (_pageIndex - 1))
            .ToListAsync();

            var areaList = _areaRepository.GetAll();
            return new PagedResultDto<BasicPersonListDto>(basicPersonCount,
                items.Select(item =>
                {
                    var dto = item.MapTo<BasicPersonListDto>();
                    var townModel = areaList.Where(p => p.Id == dto.TownID).Select(p => new { p.Title }).FirstOrDefault();
                    if (townModel != null)
                        dto.TownTitle = townModel.Title;

                    var areaModel = areaList.Where(p => p.Id == dto.AreaID).Select(p => new { p.Title }).FirstOrDefault();
                    if (areaModel != null)
                        dto.AreaTitle = areaModel.Title;

                    var villModel = areaList.Where(p => p.Id == dto.VillageID).Select(p => new { p.Title }).FirstOrDefault();
                    if (villModel != null)
                        dto.VillageTitle = villModel.Title;

                    if (dto.ParentID == 0)
                        dto.IsShow = true;
                    else
                        dto.IsShow = false;
                    return dto;
                }).ToList());
        }

        /// <summary>
        /// 通过Id获取莒县人口基本信息信息进行编辑或修改 
        /// </summary>
        public async Task<GetBasicPersonForEditOutput> GetBasicPersonForEditAPPAsync(EntityDto<string> input)
        {
            var output = new GetBasicPersonForEditOutput();

            BasicPersonEditDto basicPersonEditDto;

            if (!string.IsNullOrWhiteSpace(input.Id))
            {
                var id = Convert.ToInt32(input.Id);
                var entity = await _basicPersonRepository.GetAsync(id);
                basicPersonEditDto = entity.MapTo<BasicPersonEditDto>();
            }
            else
            {
                basicPersonEditDto = new BasicPersonEditDto();
            }

            output.BasicPerson = basicPersonEditDto;
            return output;
        }

        public virtual async Task<BasicPersonEditDto> CreateBasicPersonAppAsync(BasicPersonAPPEditDto input)
        {
            //TODO:新增前的逻辑判断，是否允许新增

            var entity = input.MapTo<BasicPerson>();
            entity = await _basicPersonRepository.InsertAsync(entity);
            return entity.MapTo<BasicPersonEditDto>();
        }

        /// <summary>
        /// 编辑实有房屋、人口
        /// </summary>
        public virtual async Task UpdateBasicPersonAppAsync(BasicPersonAPPEditDto input)
        {
            //TODO:更新前的逻辑判断，是否允许更新
            var id = Convert.ToInt32(input.Id);
            var entity = await _basicPersonRepository.GetAsync(id);
            input.MapTo(entity);

            await _basicPersonRepository.UpdateAsync(entity);
        }

        /// <summary>
        /// 删除实有房屋、人口
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task DeleteBasicPersonAppAsync(EntityDto<string> input)
        {
            //TODO:删除前的逻辑判断，是否允许删除
            //先删除子节点
            var id = Convert.ToInt32(input.Id);
            await _basicPersonRepository.DeleteAsync(s => s.ParentID == id);

            await _basicPersonRepository.DeleteAsync(id);
        }
        #endregion

    }
}
